﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace DrawCircles
{
    class DrawCircles : Window
    {
        Canvas canvas;
        bool isDrawing;
        Ellipse elips;
        Point ptCenter;
        bool isDragging;
        FrameworkElement elDragging;
        Point ptMouseStart, ptElementStart;

        public DrawCircles()
        {
            this.Title = "Draw Circles";
            this.Content = this.canvas = new Canvas();
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            if (this.isDragging)
            {
                return;
            }

            this.ptCenter = e.GetPosition(this.canvas);
            this.elips = new Ellipse()
            {
                Stroke = SystemColors.WindowTextBrush,
                StrokeThickness = 1,
                Width = 0,
                Height = 0
            };
            this.canvas.Children.Add(this.elips);
            Canvas.SetLeft(this.elips, ptCenter.X);
            Canvas.SetTop(this.elips, ptCenter.Y);

            this.CaptureMouse();
            this.isDrawing = true;
        }

        protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseRightButtonDown(e);

            if (this.isDrawing)
            {
                return;
            }

            this.ptMouseStart = e.GetPosition(this.canvas);
            this.elDragging = this.canvas.InputHitTest(this.ptMouseStart) as FrameworkElement;

            if (this.elDragging != null)
            {
                this.ptElementStart = new Point(Canvas.GetLeft(this.elDragging), Canvas.GetTop(this.elDragging));
                this.CaptureMouse();
                this.isDragging = true;
            }
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);

            if (e.ChangedButton == MouseButton.Middle)
            {
                Shape shape = this.canvas.InputHitTest(e.GetPosition(this.canvas)) as Shape;
                if (shape != null)
                {
                    shape.Fill = (shape.Fill == Brushes.Red ? Brushes.Transparent : Brushes.Red);
                }
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            Point ptMouse = e.GetPosition(this.canvas);
            if (this.isDrawing)
            {
                double dRadius = Math.Sqrt(Math.Pow(this.ptCenter.X - ptMouse.X, 2) + Math.Pow(this.ptCenter.Y - ptMouse.Y, 2));
                Canvas.SetLeft(this.elips, this.ptCenter.X - dRadius);
                Canvas.SetTop(this.elips, this.ptCenter.Y - dRadius);
                this.elips.Width = 2 * dRadius;
                this.elips.Height = 2 * dRadius;
            }
            else if (this.isDragging)
            {
                Canvas.SetLeft(this.elDragging, this.ptElementStart.X + ptMouse.X - this.ptMouseStart.X);
                Canvas.SetTop(this.elDragging, this.ptElementStart.Y + ptMouse.Y - this.ptMouseStart.Y);
            }
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            if (this.isDrawing && e.ChangedButton == MouseButton.Left)
            {
                this.elips.Stroke = Brushes.Blue;
                this.elips.StrokeThickness = Math.Min(24, this.elips.Width / 2);
                this.elips.Fill = Brushes.Red;

                this.isDrawing = false;
                this.ReleaseMouseCapture();
            }
            else if (this.isDragging && e.ChangedButton == MouseButton.Right)
            {
                this.isDragging = false;
                this.ReleaseMouseCapture();
            }
        }

        protected override void OnTextInput(TextCompositionEventArgs e)
        {
            base.OnTextInput(e);
            if (e.Text.IndexOf('\x1B') != -1)
            {
                if (this.isDrawing)
                {
                    this.ReleaseMouseCapture();
                }
                else if (this.isDragging)
                {
                    this.ReleaseMouseCapture();
                }
            }
        }

        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            base.OnLostMouseCapture(e);
            if (this.isDrawing)
            {
                this.canvas.Children.Remove(this.elips);
                this.isDrawing = false;
            }
            else if (this.isDragging)
            {
                Canvas.SetLeft(this.elDragging, this.ptElementStart.X);
                Canvas.SetTop(this.elDragging, this.ptElementStart.Y);
                this.isDragging = false;
            }
        }

        [STAThread]
        public static void Main()
        {
            Application app = new Application();
            app.Run(new DrawCircles());
        }
    }
}
